package com.yyh.synctool.client.component;

import com.yyh.common.IOCommon;
import com.yyh.common.JsonCommon;
import com.yyh.pojo.SyncParam;
import com.yyh.synctool.client.constant.DB;
import com.yyh.synctool.client.tool.TaskMapper;
import com.yyh.synctool.client.job.TaskId;
import com.yyh.synctool.client.tool.ConfigKey;
import com.yyh.synctool.client.tool.DBHelper;
import okhttp3.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.io.*;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.List;
import java.util.Map;

/**
 * 改进方案：一个TaskHelper代表一个任务，数据源等作为bean注入
 * @author xuan
 * @date 2021/12/14
 */
@Component
public class TaskHelper
{
    private Setting setting;
    private DBHelper dbHelper;
    private ThisApplicationContext thisApplicationContext;
    /** 数据库状态 */
    private boolean available = false;
    /** 库存任务 服务端接口 */
    @Value("${synctool.server.stock}")
    private String stockUrl;
    /** namespace */
    private static final String NAMESPACE = "com.yyh.synctool.client.tool.TaskMapper";
    /** xml文件名 */
    private static final String XML_NAME = "TaskMapper.xml";

    @Autowired
    public TaskHelper(ThisApplicationContext thisApplicationContext, Setting setting) {
        this.thisApplicationContext = thisApplicationContext;
        this.setting = setting;
        this.dbHelper = new DBHelper();
        init();
    }

    /** 执行指定任务 */
    public void execute(String taskId) throws Exception {
        if (setting.isChanged()) {
            // 设置被更改
            init();
        }
        // 执行taskId指定的任务
        switch (taskId) {
            case TaskId.STOCK: stockSync(); break;
            case TaskId.PRICE: priceSync(); break;
        }
    }

    /** 库存任务 */
    public void stockSync() throws IOException {
        TaskMapper mapper = dbHelper.getMapper(TaskMapper.class);
        List<Map> stock = mapper.findStock();
        SyncParam<List<Map>> syncParam = new SyncParam<>();
        // 添加验证信息
        syncParam.setGsid(setting.getGsid());
        syncParam.setCredential(setting.getCredential());
        syncParam.setData(stock);
        String jsonString = JsonCommon.toJsonString(syncParam);

        // 发送请求，获取响应
        OkHttpClient okHttpClient = new OkHttpClient().newBuilder().build();
        Request request = new Request.Builder()
                .url(stockUrl)
                .post(RequestBody.create(jsonString, MediaType.parse("application/json; charset=UTF-8")))
                .build();

        Response response = okHttpClient.newCall(request).execute();

        String str = response.body().string();
        System.out.println(str);

        // 请求失败抛出异常
    }

    /** 价格任务 */
    public void priceSync() {
        TaskMapper mapper = dbHelper.getMapper(TaskMapper.class);
        List<Map> price = mapper.findPrice();

    }

    /**
     * 初始化DBHelper
     * 数据库连接配置被修改时，调用该方法重新加载数据源以及重新注册xml映射文件(禁用连接池)
     */
    public void init() {
        // 当前使用的数据库类型
        DB db = DB.getInstance(setting.getType());
        // 没有配置数据库时，不进行初始化
        if (null == db) { return; }
        String driverName = db.getDriverName();
        String url = setting.getUrl();
        String username = setting.getUsername();
        String password = setting.getPassword();

        this.dbHelper.init(driverName, url, username, password);
        //this.dbHelper.registryMapper(NAMESPACE, loadMapperXML());
        this.dbHelper.registryMapper(NAMESPACE, generateMapperXML(NAMESPACE));
    }

    /** 加载磁盘上的xml映射文件 */
    public String loadMapperXML() {
        String xml = "";
        Path filePath = thisApplicationContext.getRootDir().resolve(XML_NAME);
        try {
            xml = IOCommon.readAsString(new FileInputStream(filePath.toFile()));
        } catch (FileNotFoundException e) {
            // 文件不存在
            return xml;
        }
        return xml;
    }

    /** mybatis中TaskMapper接口 的xml映射文件生成，写入磁盘并返回 */
    public String generateMapperXML(String namespace) {
        StringBuilder xml = new StringBuilder();
        xml.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
        xml.append("<!DOCTYPE mapper PUBLIC \"-//mybatis.org//DTD Mapper 3.0//EN\"\n");
        xml.append("        \"http://mybatis.org/dtd/mybatis-3-mapper.dtd\">\n");
        xml.append("<mapper namespace=\""+namespace+"\">\n");

        xml.append("    <select id=\"findStock\" resultType=\"Map\">\n");
        xml.append("        "+setting.getTaskSql(ConfigKey.TASK_STOCK)+"\n");
        xml.append("    </select>\n");
        xml.append("\n");

        xml.append("    <select id=\"findPrice\" resultType=\"Map\">\n");
        xml.append("        "+setting.getTaskSql(ConfigKey.TASK_PRICE)+"\n");
        xml.append("    </select>\n");
        xml.append("\n");

        xml.append("</mapper>");

        Path filePath = thisApplicationContext.getRootDir().resolve(XML_NAME);
        try {
            Files.deleteIfExists(filePath);

            FileOutputStream os = new FileOutputStream(filePath.toFile());
            IOCommon.writeToString(os, xml.toString());
        } catch (IOException e) {
            // 使用中 ==>非人为操作不存在这种情况
            // 文件名中存在空格 ==>已检查
            throw new RuntimeException(e.getMessage(), e.getCause());
        }

        return xml.toString();
    }
}
